﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using SHomeWorkshop.LunarPresentation.Converts;
using SHomeWorkshop.LunarPresentation.Dialogs;
using SHomeWorkshop.LunarPresentation.Interfaces;

namespace SHomeWorkshop.LunarPresentation
{
    public enum TypeOfExpression
    {
        Arrow, BaseText, Brace, Bracket, Expander, Grid, GridPanel,
        LogicCross, LogicGenuspecies, LogicContradiction, MarkText,
        PictureBox, RichText, Row, SubPanel, Triangle, UnKnow,
        Tree
    }

    public static class Globals
    {
        static Globals()
        {
            baseActiveBackGround = new LinearGradientBrush();
            baseActiveBackGround.StartPoint = new Point(0, 0);
            baseActiveBackGround.EndPoint = new Point(0, 1);
            baseActiveBackGround.GradientStops.Add(new GradientStop(Colors.LightCyan, 0.0));
            baseActiveBackGround.GradientStops.Add(new GradientStop(Colors.Transparent, 0.2));
            baseActiveBackGround.GradientStops.Add(new GradientStop(Colors.Transparent, 0.86));
            baseActiveBackGround.GradientStops.Add(new GradientStop(Colors.LightCyan, 1.0));

            commandLineList = new List<string>();

            globalDataSetIn = new DataSet();
            Globals.globalDataSetIn.Tables.Add("Expressions");


            pathOfUserDirectory = pathOfMyDocuments + "\\SHome WorkShop\\Lunar Presentation\\";

            pathOfUserTemplateDocuments = pathOfUserDirectory + "Templates\\";

            if (installedPath.EndsWith("\\"))
            {
                pathOfSystemTemplateDocuments = installedPath + "Templates\\";
            }
            else
            {
                pathOfSystemTemplateDocuments = installedPath + "\\Templates\\";
            }

            pathofUserDocuments = pathOfUserDirectory + "Documents\\";

            pathOfExpressionDatabase = pathOfUserDirectory + "LunarExpressions.mdb";
            if (System.IO.Directory.Exists(pathOfUserDirectory) == false)
            {
                System.IO.Directory.CreateDirectory(pathOfUserDirectory);
            }

            pathOfPreferences = pathOfUserDirectory + "Preferences.xml";

            pathOfRecentlyFiles = pathOfUserDirectory + "RecentlyFiles.xml";

            pathOfDefAuthorInfoXmlFile = pathOfUserDirectory + "DefAuthorInfo.xml";

            //初始化颜色拾取器。
            ColorPicker colorPicker = new ColorPicker();
            colorPicker.ColorPicked += new EventHandler<ColorPickedEventArgs>(colorPicker_ColorPicked);
            colorPicker.Closed += new EventHandler<EventArgs>(colorPicker_Closed);

            colorPickerPopup.StaysOpen = false;
            colorPickerPopup.Child = colorPicker;

            Globals.textCmdList = new TextCmdList();
        }

        static void colorPicker_Closed(object sender, EventArgs e)
        {
            colorPickerPopup.IsOpen = false;
        }

        static void colorPicker_ColorPicked(object sender, ColorPickedEventArgs e)
        {
            //Globals.colorPickerPopup.IsOpen = false;

            SetExpressionColor((sender as ColorPicker).DestAction, e.PickedColor);
        }

        static void SetExpressionColor(ColorPicker.Destination dest, Brush newBrush)
        {
            if (Globals.selectedEditor == null) return;

            switch (dest)
            {
                case ColorPicker.Destination.Border:
                    {
                        if (Globals.selectedEditor.SelectedExpression == null) return;
                        Expressions.Expression ex = Globals.selectedEditor.SelectedExpression;
                        ModifingItem mi = new ModifingItem();
                        Action action = new Action(ex.ExID, -1, ex.GetType().Name, "BorderColor",
                            ColorPicker.GetBrushName(ex.BorderColor), ColorPicker.GetBrushName(newBrush));

                        Globals.selectedEditor.SelectedExpression.BorderColor = newBrush;

                        mi.Add(action);
                        ex.Editor.Do(mi);
                        break;
                    }
                case ColorPicker.Destination.Background:
                    {
                        if (Globals.selectedEditor.SelectedExpression == null) return;
                        Expressions.Expression ex = Globals.selectedEditor.SelectedExpression;
                        ModifingItem mi = new ModifingItem();
                        Action action = new Action(ex.ExID, -1, ex.GetType().Name, "ExBackground",
                            ColorPicker.GetBrushName(ex.ExBackground), ColorPicker.GetBrushName(newBrush));

                        Globals.selectedEditor.SelectedExpression.ExBackground = newBrush;

                        mi.Add(action);
                        ex.Editor.Do(mi);
                        break;
                    }
                case ColorPicker.Destination.Foreground:
                    {
                        if (Globals.selectedEditor.SelectedExpression == null) return;
                        Expressions.Expression ex = Globals.selectedEditor.SelectedExpression;

                        ModifingItem mi = new ModifingItem();
                        Action action = new Action(ex.ExID, -1, ex.GetType().Name, "ExForeground",
                            ColorPicker.GetBrushName(ex.ExForeground), ColorPicker.GetBrushName(newBrush));

                        Globals.selectedEditor.SelectedExpression.ExForeground = newBrush;

                        mi.Add(action);
                        ex.Editor.Do(mi);
                        break;
                    }
            }
        }

        public static string pathOfPreferences = null;

        public static string pathOfRecentlyFiles = null;

        /// <summary>
        /// 保存公式到数据库时，默认的“作者信息”。
        /// </summary>
        public static string pathOfDefAuthorInfoXmlFile = null;

        #region 数据库相关
        public static string pathOfMyDocuments = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

        /// <summary>
        /// pathOfMyDocuments + "\\SHome WorkShop\\Lunar Presentation\\LunarExpressions.mdb";
        /// </summary>
        public static string pathOfExpressionDatabase;

        /// <summary>
        /// 以"\"结尾。
        /// </summary>
        public static string pathOfUserDirectory;

        /// <summary>
        /// 用户自定义模板存放目录。
        /// </summary>
        public static string pathOfUserTemplateDocuments;

        public static string pathofUserDocuments;

        /// <summary>
        /// 系统自带模板存放目录。
        /// </summary>
        public static string pathOfSystemTemplateDocuments;

        public static string dataBaseKey = "DyBj#PpBb";

        public static System.Data.OleDb.OleDbDataAdapter globalDataAdapter = null;

        public static DataSet globalDataSetIn = null;

        public static System.Data.OleDb.OleDbConnection globalConnection = null;

        public static bool SaveExpressionToDataBase(System.Xml.XmlNode expressionNode, string defKeyWord)
        {
            if (globalDataSetIn.Tables.Contains("Expressions") == false)
            {
                System.Windows.MessageBox.Show("数据集中无“Expression”表！", Globals.appName,
                    MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }

            if (expressionNode == null)
            {
                System.Windows.MessageBox.Show("要保存的公式节点为null！", Globals.appName,
                    MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }

            System.Xml.XmlAttribute attrType = expressionNode.GetAttribute("Type");
            if (attrType == null)
            {
                System.Windows.MessageBox.Show("公式节点中无“Type”特性！", Globals.appName,
                    MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }

            if (attrType.Value == "SubPanel")
            {
                System.Windows.MessageBox.Show("不能将子面板写入数据库！", Globals.appName,
                    MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }

            if (Globals.globalConnection == null)
            {
                System.Windows.MessageBox.Show("未能建立数据库连接！", Globals.appName,
                    MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }

            ExRecordInfo eriDialog = new ExRecordInfo(null, null, null) { Owner = Globals.MainWindow };

            if (defKeyWord != null)
            {
                eriDialog.tbxKeyWord.Text = defKeyWord;
                eriDialog.tbxKeyWord.SelectAll();
            }

            Globals.SwitchInputMethod(true);
            bool? resultOfDialog = eriDialog.ShowDialog();
            Globals.SwitchInputMethod(false);//无论如何，只要对话框关闭，即自动禁用输入法。

            if (resultOfDialog != true) return false;//取消入库操作。

            Globals.globalConnection.Open();
            DataTable exTable = Globals.globalDataSetIn.Tables["Expressions"];

            string dateTimeString = System.DateTime.Now.ToString();

            string insertStr = "INSERT INTO Expressions (KeyWord,ExpressionXml,AuthorInfo,ModifiedTime,SaveTime,Comment) VALUES ('"
                        + eriDialog.KeyWord + "','" + expressionNode.OuterXml + "','"
                        + eriDialog.AuthorInfo + "','" + dateTimeString + "','"
                        + dateTimeString + "','" + eriDialog.Comment + "')";
            OleDbCommand myCommand = new OleDbCommand(insertStr, Globals.globalConnection);
            try
            {
                myCommand.ExecuteNonQuery();

                myCommand.CommandText = "SELECT MAX(ID) FROM Expressions";
                int maxNum = (int)myCommand.ExecuteScalar();
                DataRow r = exTable.NewRow();
                r.BeginEdit();
                r["ID"] = maxNum;
                r["KeyWord"] = eriDialog.KeyWord;
                r["ExpressionXml"] = expressionNode.OuterXml;
                r["AuthorInfo"] = eriDialog.AuthorInfo;
                r["ModifiedTime"] = dateTimeString;
                r["SaveTime"] = dateTimeString;
                r["Comment"] = eriDialog.Comment;
                r.EndEdit();
                exTable.Rows.Add(r);

                Globals.globalConnection.Close();
            }
            finally
            {
                myCommand.Dispose();
            }
            return true;
        }


        #endregion

        public static string installedPath = System.AppDomain.CurrentDomain.BaseDirectory;

        /// <summary>
        /// 用以搜索文档内容的关键词。
        /// </summary>
        public static string findText = null;

        public static List<string> commandLineList;

        //public static LinearGradientBrush brushForSelectedExpression;

        //public static LinearGradientBrush brushForSelectedSubPanel;

        public static LinearGradientBrush baseActiveBackGround;

        //public static Brush expanderHandleBrush = Brushes.LightGray;

        //public static LinearGradientBrush expressionIndentHandleBrush;

        /// <summary>
        /// 此变量专用于新建文档时计算已新建了多少个。
        /// </summary>
        public static int newDocumentsCount = 0;

        public static System.Xml.Linq.XDocument templateXDoc = null;

        public static Editor selectedEditor;

        public static Thickness defaultBorderThickness = new Thickness(1);

        public static MarginConverter marginConverter = new MarginConverter();

        public static TextFontSizeLevelConverter textFontSizeConverter =
            new TextFontSizeLevelConverter();

        public static MaxWidthConverter maxWidthConverter = new MaxWidthConverter();

        public static MarkTextSizeConverter markTextSizeConverter = new MarkTextSizeConverter();

        public static HalfTextSizeConverter halfTextSizeConverter = new HalfTextSizeConverter();

        public static BaseTextCommentFontSizeConverter baseTextCommentFontSizeConverter = new BaseTextCommentFontSizeConverter();

        public static BaseTextCommentIndentConverter baseTextCommentIndentConverter = new BaseTextCommentIndentConverter();

        /// <summary>
        /// 终于解决了输入法的问题。
        /// 原先使用WinForm的输入法控制库终究不行——取不出当前输入法名称。
        /// </summary>
        /// <param name="enable"></param>
        public static void SwitchInputMethod(bool enable)
        {
            if (MainWindow == null) return;

            InputMethod.SetIsInputMethodEnabled(MainWindow, false);

            InputMethod.Current.ImeState = enable ? InputMethodState.On : InputMethodState.Off;
        }

        public static string ShowInputBox(Window parentWindow,
            string promptText, string defaultText)
        {
            InputWindow iw = new InputWindow(parentWindow, promptText, defaultText, Globals.appName) { Owner = Globals.MainWindow };

            if (iw.ShowDialog() == true)
            {
                if (parentWindow != null) { parentWindow.Focus(); }
                Globals.SwitchInputMethod(false);
                return iw.InputedText;
            }

            if (parentWindow != null) { parentWindow.Focus(); }
            Globals.SwitchInputMethod(false);
            return string.Empty;
        }

        /// <summary>
        /// 刷新菜单项和工具条项目的可用状态。
        /// </summary>
        /// <param name="window"></param>
        public static void RefreshToolsWhenLastDocumentClosed(MainWindow window)
        {
            if (window == null) return;

            //window.mFile.IsEnabled = true;//“文件”菜单。
            //window.miNewDocument.IsEnabled = true;
            //window.miOpenDocument.IsEnabled = true;
            //window.miExit.IsEnabled = true;

            window.miSaveDocument.IsEnabled = false;
            window.miSaveDocumentAs.IsEnabled = false;
            window.miSaveAllDocument.IsEnabled = false;
            window.miOutportDocumentToImage.IsEnabled = false;
            window.miCloseSelectedDocument.IsEnabled = false;

            //window.mHelp.IsEnabled = true;//“帮助”菜单。
            //window.miHelp.IsEnabled = true;
            //window.miAbout.IsEnabled = true;

            window.mEdit.IsEnabled = false;
            window.mInsert.IsEnabled = false;
            window.mEmbed.IsEnabled = false;
            window.mFormat.IsEnabled = false;
            window.mGrid.IsEnabled = false;
            window.mTools.IsEnabled = false;

            //=========ToolBar==============
            window.btnSave.IsEnabled = false;

            //=========DataBaseList============
            if (pathOfExpressionDatabase != null)
            {
                //window.tiFindInDataBase.Visibility = Visibility.Hidden;
                window.dataBaseList.Visibility = Visibility.Hidden;
                window.gcAssist.Width = new GridLength(0);
            }

            window.toolTabSplitter.IsEnabled = false;

            //改写了Find()方法。
            //window.spFindResult.Children.Clear();
            //window.spFindResult.Visibility = Visibility.Hidden;

            RefreshToolBarItemsWhenExpressionSelected(window);
        }

        /// <summary>
        /// ★★菜单各项目的可用状态刷新不在此处进行，也不在“公式被选中”时进行，
        /// 而是在“菜单项被弹出”时确定是否可用。
        /// 
        /// 刷新菜单项和工具条项目可用状态。
        /// </summary>
        /// <param name="window"></param>
        public static void RefreshToolsWhenNewOrOpenDocument(MainWindow window)
        {
            if (window == null) return;

            //window.mFile.IsEnabled = true;//“文件”菜单。
            //window.miNewDocument.IsEnabled = true;
            //window.miOpenDocument.IsEnabled = true;
            //window.miExit.IsEnabled = true;

            window.miSaveDocument.IsEnabled = true;
            window.miSaveDocumentAs.IsEnabled = true;
            window.miSaveAllDocument.IsEnabled = true;
            window.miOutportDocumentToImage.IsEnabled = true;
            window.miCloseSelectedDocument.IsEnabled = true;

            //window.mHelp.IsEnabled = true;//“帮助”菜单。
            //window.miHelp.IsEnabled = true;
            //window.miAbout.IsEnabled = true;

            window.mEdit.IsEnabled = true;
            window.mInsert.IsEnabled = true;
            window.mEmbed.IsEnabled = true;
            window.mFormat.IsEnabled = true;
            window.mGrid.IsEnabled = true;
            window.mTools.IsEnabled = true;

            //=========ToolBar==============
            window.btnSave.IsEnabled = true;
            RefreshToolBarItemsWhenExpressionSelected(window);

            //=========DataBaseList============
            if (pathOfExpressionDatabase != null)
            {
                //window.tiFindInDataBase.Visibility = Visibility.Visible;
                window.dataBaseList.Visibility = Visibility.Visible;
            }

            window.toolTabSplitter.IsEnabled = true;

            //改写了Find()方法。
            //window.spFindResult.Visibility = Visibility.Visible;
        }

        /// <summary>
        /// ToolBar上的各项功能只能在此处刷新。
        /// </summary>
        /// <param name="window"></param>
        public static void RefreshToolBarItemsWhenExpressionSelected(MainWindow window)
        {
            if (window == null) return;

            if (Globals.selectedEditor == null ||
                Globals.selectedEditor.SelectedExpression == null)
            {
                window.btnCut.IsEnabled = false;
                window.btnCopy.IsEnabled = false;
                window.btnPaste.IsEnabled = false;

                window.btnMoveToPrevious.IsEnabled = false;
                window.btnMoveToNext.IsEnabled = false;

                window.cbFont.IsEnabled = false;
                window.cbTextHeaderLevel.IsEnabled = false;
                window.tbtnFormatBrush.IsEnabled = false;
                window.tbtnBold.IsEnabled = false;
                window.tbtnItalic.IsEnabled = false;

                window.btnExBackground.IsEnabled = false;
                window.btnExForeground.IsEnabled = false;
                window.btnExBoarderColor.IsEnabled = false;
                window.btnExEraseAllColors.IsEnabled = false;

                window.btnIndent.IsEnabled = false;
                window.btnOutdent.IsEnabled = false;

                window.btnAlignLeftOrTop.IsEnabled = false;
                window.btnAlignCenter.IsEnabled = false;
                window.btnAlignRightOrBottom.IsEnabled = false;
                window.btnAlignDefault.IsEnabled = false;
            }
            else
            {
                bool notSubPanel = !(Globals.selectedEditor.SelectedExpression is Expressions.SubPanel);

                if (!notSubPanel)
                {
                    Expressions.LeafPanel lp = Globals.selectedEditor.SelectedExpression as Expressions.LeafPanel;
                    if (lp == null || lp.LeafType == Expressions.LeafPanel.LeafPanelType.Root)
                    {
                        window.btnCut.IsEnabled = false;
                        window.btnCopy.IsEnabled = false;
                    }
                    else
                    {
                        window.btnCut.IsEnabled = true;
                        window.btnCopy.IsEnabled = true;
                    }
                }
                else
                {
                    window.btnCut.IsEnabled = notSubPanel;
                    window.btnCopy.IsEnabled = notSubPanel;
                }

                string clipboardText = Clipboard.GetText(TextDataFormat.UnicodeText);
                BitmapSource clipboardImg = Clipboard.GetImage();
                if ((clipboardText != null && clipboardText.Length > 0) ||
                    clipboardImg != null)
                {
                    window.btnPaste.IsEnabled = true;
                }
                else
                {
                    window.btnPaste.IsEnabled = false;
                }

                if (notSubPanel)
                {
                    if (Globals.selectedEditor.SelectedExpression.Parent is StackPanel)
                    {
                        StackPanel sp = Globals.selectedEditor.SelectedExpression.Parent as StackPanel;
                        int index = sp.Children.IndexOf(Globals.selectedEditor.SelectedExpression);
                        if (index <= 0)
                        {
                            window.btnMoveToPrevious.IsEnabled = false;
                        }
                        else
                        {
                            window.btnMoveToPrevious.IsEnabled = true;
                        }

                        if (index >= sp.Children.Count - 1)
                        {
                            window.btnMoveToNext.IsEnabled = false;
                        }
                        else
                        {
                            window.btnMoveToNext.IsEnabled = true;
                        }
                    }
                }
                else
                {
                    window.btnMoveToPrevious.IsEnabled = false;
                    window.btnMoveToNext.IsEnabled = false;
                }

                bool isBaseText = Globals.selectedEditor.SelectedExpression is Expressions.BaseText;
                bool isMarkText = Globals.selectedEditor.SelectedExpression is Expressions.MarkText;
                window.cbFont.IsEnabled = isBaseText || isMarkText;
                window.cbTextHeaderLevel.IsEnabled = isBaseText || isMarkText;
                window.tbtnFormatBrush.IsEnabled = isBaseText;
                window.tbtnBold.IsEnabled = isBaseText || isMarkText;
                window.tbtnItalic.IsEnabled = isBaseText || isMarkText;

                if (!isBaseText && !isMarkText)
                {
                    window.tbtnBold.IsChecked = false;
                    window.tbtnItalic.IsChecked = false;
                }

                window.btnExBackground.IsEnabled = true;
                window.btnExBoarderColor.IsEnabled = true;

                //只有前景色，不是所有公式都有意义。
                Expressions.Expression ex = Globals.selectedEditor.SelectedExpression;
                if (ex is Expressions.Bracket || ex is Expressions.BaseText ||
                    ex is Expressions.Arrow || ex is Expressions.Brace ||
                    ex is Expressions.MarkText || ex is Expressions.CanvasExpression)
                {
                    window.btnExForeground.IsEnabled = true;
                }
                else
                {
                    window.btnExForeground.IsEnabled = false;
                }

                window.btnExEraseAllColors.IsEnabled = true;

                #region 刷新字体，注意禁用/启用字体被改变事件
                window.ForbiddenFontChangedEvent = true;
                window.ForbiddenFontSizeLevelEvent = true;

                if (isBaseText)
                {
                    Expressions.BaseText bt = Globals.selectedEditor.SelectedExpression as Expressions.BaseText;
                    if (bt.FontName == null || bt.FontName == "")
                    {

                        if (window.cbFont.Items.Contains(Globals.SysFontFamily))
                        {
                            window.cbFont.SelectedItem = Globals.SysFontFamily;
                        }
                    }
                    else
                    {
                        window.cbFont.SelectedItem = bt.FontName;
                    }

                    window.RefreshFontSizeLevel(bt.FontSizeLevel);

                    window.tbtnBold.IsChecked = (bt.FontWeight == FontWeights.Bold);
                    window.tbtnItalic.IsChecked = (bt.FontStyle == FontStyles.Italic);
                }
                else if (isMarkText)
                {
                    Expressions.MarkText mt = Globals.selectedEditor.SelectedExpression as Expressions.MarkText;
                    if (mt.FontName == null || mt.FontName == "")
                    {
                        if (window.cbFont.Items.Contains(Globals.SysFontFamily))
                        {
                            window.cbFont.SelectedItem = Globals.SysFontFamily;
                        }
                    }
                    else
                    {
                        window.cbFont.SelectedItem = mt.FontName;
                    }

                    window.RefreshFontSizeLevel(mt.FontSizeLevel);

                    window.tbtnBold.IsChecked = (mt.FontWeight == FontWeights.Bold);
                    window.tbtnItalic.IsChecked = (mt.FontStyle == FontStyles.Italic);
                }
                else
                {
                    window.cbFont.IsEnabled = false;
                    window.cbFont.SelectedIndex = -1;
                    window.cbTextHeaderLevel.IsEnabled = false;
                    window.cbTextHeaderLevel.SelectedIndex = -1;
                }

                window.ForbiddenFontChangedEvent = false;
                window.ForbiddenFontSizeLevelEvent = false;
                #endregion

                RefreshMainWindowIndentButtonsStatus(window, notSubPanel, ex);

                RefreshAlignButtonsStatus(window, /*notSubPanel,*/ ex);
            }
        }

        public static void RefreshAlignButtonsStatus(MainWindow window,/* bool notSubPanel,*/ Expressions.Expression ex)
        {
            if (window == null || ex == null) return;

            //2011年7月2日，着手令子面板支持指定“内部默认对齐方式”。
            //if (!notSubPanel)
            //{
            //    window.btnAlignLeftOrTop.IsEnabled = notSubPanel;
            //    window.btnAlignCenter.IsEnabled = notSubPanel;
            //    window.btnAlignRightOrBottom.IsEnabled = notSubPanel;
            //    window.btnAlignDefault.IsEnabled = notSubPanel;
            //}
            //else
            //{
            switch (ex.Align)
            {
                case Expressions.Expression.Alignment.Center:
                    {
                        window.btnAlignLeftOrTop.IsEnabled = true;
                        window.btnAlignCenter.IsEnabled = false;
                        window.btnAlignRightOrBottom.IsEnabled = true;
                        window.btnAlignDefault.IsEnabled = true;
                        break;
                    }
                case Expressions.Expression.Alignment.Default:
                    {
                        window.btnAlignLeftOrTop.IsEnabled = true;
                        window.btnAlignCenter.IsEnabled = true;
                        window.btnAlignRightOrBottom.IsEnabled = true;
                        window.btnAlignDefault.IsEnabled = false;
                        break;
                    }
                case Expressions.Expression.Alignment.LeftOrTop:
                    {
                        window.btnAlignLeftOrTop.IsEnabled = false;
                        window.btnAlignCenter.IsEnabled = true;
                        window.btnAlignRightOrBottom.IsEnabled = true;
                        window.btnAlignDefault.IsEnabled = true;
                        break;
                    }
                case Expressions.Expression.Alignment.RightOrBottom:
                    {
                        window.btnAlignLeftOrTop.IsEnabled = true;
                        window.btnAlignCenter.IsEnabled = true;
                        window.btnAlignRightOrBottom.IsEnabled = false;
                        window.btnAlignDefault.IsEnabled = true;
                        break;
                    }
            }
            //}
        }

        public static void RefreshMainWindowIndentButtonsStatus(MainWindow window, bool notSubPanel, Expressions.Expression ex)
        {
            if (window == null || ex == null) return;

            if (notSubPanel == false)
            {
                window.btnIndent.IsEnabled = notSubPanel;
                window.btnOutdent.IsEnabled = notSubPanel;
            }
            else
            {
                if (ex.ParentPanel != null)
                {
                    if (ex.ParentPanel.Direction == Orientation.Horizontal)
                    {
                        window.btnIndent.IsEnabled = false;
                        window.btnOutdent.IsEnabled = false;
                    }
                    else
                    {
                        //右对齐时，应禁用Indent和Outdent。
                        if (ex.Align == Expressions.Expression.Alignment.RightOrBottom)
                        {
                            window.btnIndent.IsEnabled = false;
                            window.btnOutdent.IsEnabled = false;
                        }
                        else
                        {
                            if (ex.Indent >= 6)
                            {
                                window.btnIndent.IsEnabled = false;
                            }
                            else
                            {
                                window.btnIndent.IsEnabled = true;
                            }

                            if (ex.Indent <= 0)
                            {
                                window.btnOutdent.IsEnabled = false;
                            }
                            else
                            {
                                window.btnOutdent.IsEnabled = true;
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 尝试显示公式。一般用于选定公式后。
        /// </summary>
        /// <param name="ex">要显示的公式。</param>
        public static void TryToShowExpressionAtTopLeft(LunarPresentation.Expressions.Expression ex)
        {
            // 尝试显示新插入的公式。
            isDraging = true;//暂时禁用拖动功能，否则若用户此时点击鼠标，会出现误拖动现象。

            //ex.InvalidateArrange();
            //ex.UpdateLayout();

            Editor editor = ex.Editor;

            System.Windows.Point startPtOfEx = ex.TranslatePoint(
                    new System.Windows.Point(0, 0), editor.BaseScrolledViewer);

            editor.BaseScrolledViewer.ScrollToHorizontalOffset(
                        startPtOfEx.X + editor.BaseScrolledViewer.HorizontalOffset - 20);

            editor.BaseScrolledViewer.ScrollToVerticalOffset(
                        startPtOfEx.Y + editor.BaseScrolledViewer.VerticalOffset - 20);

            isDraging = false;//启用拖动功能。
        }

        /// <summary>
        /// 被拖动的公式。
        /// </summary>
        public static Expressions.Expression dragSourceExpression = null;

        /// <summary>
        /// 这个变量用以防止鼠标操作过快，以致于上一次拖放操作尚未完成时就开始下一次拖放操作。
        /// </summary>
        public static bool isDraging = false;

        public static void DropExpression(Expressions.Expression destExpression)
        {
            if (Globals.isDraging || destExpression == null ||
                Globals.dragSourceExpression is Expressions.SubPanel)//子面板不允许拖动。
            {
                isDraging = false;
                return;
            }

            //禁止拖动折叠的标题文本块。
            if (Globals.dragSourceExpression is Expressions.BaseText)
            {
                Expressions.BaseText dragSourceBT = Globals.dragSourceExpression as Expressions.BaseText;
                if (dragSourceBT.IsCollapsed)
                {
                    Globals.dragSourceExpression = null;
                    Globals.isDraging = true;
                    return;
                }
            }

            //防止鼠标操作过快。
            Globals.isDraging = true;

            if (destExpression.Editor == null)
            {
                isDraging = false; return;
            }

            if (destExpression.Editor.IsOpened == false)
            {
                isDraging = false; return;
            }

            //实现拖动后放置公式。
            if (Globals.dragSourceExpression == null ||
                Globals.dragSourceExpression == destExpression ||
                Globals.dragSourceExpression.Editor != destExpression.Editor)//不允许跨文档拖动。
            {
                isDraging = false;
                return;//不能拖动到自身。
            }

            if (Globals.dragSourceExpression.ParentPanel == destExpression.ParentPanel)
            {
                if (destExpression.ParentPanel.BasePanel.Children.IndexOf(Globals.dragSourceExpression) ==
                    destExpression.ParentPanel.BasePanel.Children.IndexOf(destExpression) - 1)
                {
                    //拖动源正好在当前目标公式前面一个位置，这根本就没必要拖动。
                    Globals.dragSourceExpression = null;
                    isDraging = false;
                    return;
                }
            }

            bool forefather = false;
            Expressions.Expression ex = destExpression.ParentPanel;
            while (ex != null)
            {
                if (ex == Globals.dragSourceExpression)
                {
                    forefather = true;
                    break;
                }

                if (ex is Expressions.SubPanel)
                {
                    ex = (ex as Expressions.SubPanel).ParentExpression;
                }
                else
                {
                    ex = ex.ParentPanel;
                }
            }

            //不能把公式拖动到自身内部。
            if (forefather)
            {
                System.Windows.MessageBox.Show("不能把一个公式拖动到自身内部！",
                    Globals.appName, MessageBoxButton.OK, MessageBoxImage.Warning);
                Globals.dragSourceExpression = null;
                isDraging = false;
                return;
            }

            //下面是将源公式移动到新位置。
            //如果被拖动的公式是所在子面板中唯一的公式，应向该子面板添加一个文本块。

            Expressions.SubPanel srcPanel = Globals.dragSourceExpression.ParentPanel;

            ModifingItem mi = new ModifingItem();

            if (Globals.dragSourceExpression.ParentPanel.BasePanel.Children.Count == 1)
            {
                Expressions.SubPanel parentSourcePanel = Globals.dragSourceExpression.ParentPanel;
                Globals.dragSourceExpression.XmlData.InsertXml(
                    LunarPresentation.Properties.Resources.BaseText, true);
                Expressions.BaseText bt = new Expressions.BaseText(Globals.dragSourceExpression.RootPanel, parentSourcePanel,
                    Globals.dragSourceExpression.Editor);

                parentSourcePanel.BasePanel.Children.Insert(1, bt);
                bt.XmlData = Globals.dragSourceExpression.XmlData.NextSibling;

                Action actionInsertBaseText = new Action(bt.ExID, parentSourcePanel.BasePanel.Children.IndexOf(bt),
                    bt.GetType().Name, "InsertExpression", null, bt.XmlData.OuterXml, ActionType.Insert,
                    parentSourcePanel.ExID);
                mi.Add(actionInsertBaseText);
            }

            Action actionDelSourceEx = new Action(Globals.dragSourceExpression.ExID,
                Globals.dragSourceExpression.ParentPanel.BasePanel.Children.IndexOf(Globals.dragSourceExpression),
                Globals.dragSourceExpression.GetType().Name, "DeleteExpression",
                Globals.dragSourceExpression.XmlData.OuterXml, null,
                ActionType.Delete, Globals.dragSourceExpression.ParentPanel.ExID);
            mi.Add(actionDelSourceEx);

            Globals.dragSourceExpression.XmlData.ParentNode.RemoveChild(
                Globals.dragSourceExpression.XmlData);
            Globals.dragSourceExpression.ParentPanel.BasePanel.Children.Remove(
                Globals.dragSourceExpression);

            destExpression.ParentPanel.XmlData.InsertBefore(Globals.dragSourceExpression.XmlData, destExpression.XmlData);
            destExpression.ParentPanel.BasePanel.Children.Insert(
                destExpression.ParentPanel.BasePanel.Children.IndexOf(destExpression),
                Globals.dragSourceExpression);

            Globals.dragSourceExpression.ParentPanel = destExpression.ParentPanel;

            //Globals.dragSourceExpression.Editor = destExpression.Editor;
            //Globals.dragSourceExpression.RootPanel = destExpression.RootPanel;
            //跨编辑器拖动是不被支持的，跨进程实例就更不支持了。因此，此两行多余。

            Action actionInsertToDestEx = new Action(Globals.dragSourceExpression.ExID,
                Globals.dragSourceExpression.ParentPanel.BasePanel.Children.IndexOf(Globals.dragSourceExpression),
                Globals.dragSourceExpression.GetType().Name, "InsertExpression", null,
                Globals.dragSourceExpression.XmlData.OuterXml, ActionType.Insert,
                Globals.dragSourceExpression.ParentPanel.ExID);
            mi.Add(actionInsertToDestEx);

            //已经禁止在不同编辑器之间相互拖动，因此此处不考虑多编辑器的情况。
            destExpression.Editor.Do(mi);

            destExpression.Editor.IsModified = true;

            Globals.dragSourceExpression = null;

            //拖放结束。
            Globals.isDraging = false;

            Expressions.SubPanel destPanel = destExpression.ParentPanel;

            srcPanel.RefreshAutoNumbersOfBaseText();
            srcPanel.RefreshTreeLinesOfHeaderText();

            if (destPanel != srcPanel)
            {
                destPanel.RefreshAutoNumbersOfBaseText();
                destPanel.RefreshTreeLinesOfHeaderText();
            }
        }

        public static MainWindow MainWindow { get; set; }

        public static string SysFontFamily { get; set; }

        public static bool SelectFirstChildExpression()
        {
            if (Globals.selectedEditor == null) return false;
            if (Globals.selectedEditor.SelectedExpression == null)
            {
                if (Globals.selectedEditor.RootPanel != null)
                {
                    Globals.selectedEditor.SelectedExpression =
                        Globals.selectedEditor.RootPanel;
                }
                else
                {
                    MessageBox.Show("必须先选中一个拥有内嵌公式的公式，然后才能执行“选中内嵌的首公式”这一命令。",
                        Globals.appName, MessageBoxButton.OK, MessageBoxImage.Warning);
                    return false;
                }
            }

            if (Globals.selectedEditor.SelectedExpression.FirstSubPanel == null)
            {
                if (Globals.selectedEditor.SelectedExpression is Expressions.SubPanel)
                {
                    Expressions.SubPanel subPanel = Globals.selectedEditor.SelectedExpression as Expressions.SubPanel;

                    if (subPanel.BasePanel.Children.Count > 0)
                    {
                        Globals.selectedEditor.SelectedExpression =
                            subPanel.BasePanel.Children[0] as Expressions.Expression;
                        return true;
                    }
                    else
                    {
                        MessageBox.Show("发生极其意外的错误——首子面板中竟然会没有公式。",
                            Globals.appName, MessageBoxButton.OK, MessageBoxImage.Warning);
                        return false;
                    }
                }
                else
                {
                    MessageBox.Show("当前选中的公式并没有内嵌的子级公式，无法选中其“内嵌的首公式”。",
                        Globals.appName, MessageBoxButton.OK, MessageBoxImage.Warning);
                    return false;
                }
            }

            StackPanel basePanel = Globals.selectedEditor.SelectedExpression.FirstSubPanel.BasePanel;

            if (basePanel.Children.Count > 0)
            {
                Globals.selectedEditor.SelectedExpression = basePanel.Children[0] as Expressions.Expression;
                return true;
            }
            else
            {
                MessageBox.Show("发生极其意外的错误——首子面板中竟然会没有公式。",
                    Globals.appName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }
        }

        public static bool SelectLastChildExpression()
        {
            if (Globals.selectedEditor == null) return false;
            if (Globals.selectedEditor.SelectedExpression == null)
            {
                if (Globals.selectedEditor.RootPanel != null)
                {
                    Globals.selectedEditor.SelectedExpression =
                        Globals.selectedEditor.RootPanel;
                }
                else
                {
                    MessageBox.Show("必须先选中一个拥有内嵌子级公式的公式，然后才能执行“选中内嵌的首公式”这一命令。",
                        Globals.appName, MessageBoxButton.OK, MessageBoxImage.Warning);
                    return false;
                }
            }

            if (Globals.selectedEditor.SelectedExpression.LastSubPanel == null)
            {
                if (Globals.selectedEditor.SelectedExpression is Expressions.SubPanel)
                {
                    Expressions.SubPanel subPanel = Globals.selectedEditor.SelectedExpression as Expressions.SubPanel;

                    if (subPanel.BasePanel.Children.Count > 0)
                    {
                        Globals.selectedEditor.SelectedExpression =
                            subPanel.BasePanel.Children[subPanel.BasePanel.Children.Count - 1] as Expressions.Expression;
                        return true;
                    }
                    else
                    {
                        MessageBox.Show("发生极其意外的错误——尾子面板中竟然会没有公式。",
                            Globals.appName, MessageBoxButton.OK, MessageBoxImage.Warning);
                        return false;
                    }
                }
                else
                {
                    MessageBox.Show("当前选中的公式并没有内嵌的子级公式，无法选中其“内嵌的尾公式”。",
                        Globals.appName, MessageBoxButton.OK, MessageBoxImage.Warning);
                    return false;
                }
            }

            StackPanel basePanel = Globals.selectedEditor.SelectedExpression.LastSubPanel.BasePanel;

            if (basePanel.Children.Count > 0)
            {
                Globals.selectedEditor.SelectedExpression =
                    basePanel.Children[basePanel.Children.Count - 1] as Expressions.Expression;//最后一个公式。
                return true;
            }
            else
            {
                MessageBox.Show("发生极其意外的错误——尾子面板中竟然会没有公式。",
                    Globals.appName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }
        }

        /// <summary>
        /// 默认通配式的Xml文本。
        /// </summary>
        public static string wildcardExpressionXmlString = "<Expression Type=\"PictureBox\" Indent=\"0\"><Image>"
            + "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAei"
            + "YAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAALEgAACxIB0t1+/AAAARBJREFUOE9j+P//PwM6Tuh5"
            + "woxNHJsYhmaQIqABMkDMRIwhWA0onPX8f/zkt0rEGILVgNyZz/4ndN/7HzfhtQYh72A1IGPK0//z9v/+H9Rw8zXQAFt8huAKg/"
            + "+z9/3637n173+30sv/gQbY4zIEqwGRXY/+T9n263/J0r//E6b//W+TexanIVgNCGx++L917XuwZuOSL/+lo6/9N45c9t+h6Gw8"
            + "ukuwGuBRdf9/ydx3cM2KLj3/pX1WBxKdDuxL7/4PbHkGthmieaUXrjSB1QUWeXf+2xRcgWm2wZegsBpgmHUbrFnKa7krVs1ZVv"
            + "BUitUAnbQbQGev8SU7KUt5r/WT9l5BVIbC6gJibIapodgAAHZi05z8kGvDAAAAAElFTkSuQmCC</Image></Expression>";

        /// <summary>
        /// 用于“取、置左缩进值”这两个功能——类似于格式刷。
        /// </summary>
        public static int formatIndentLevel = 0;

        public static string appName = ((AssemblyTitleAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false)[0]).Title;

        public static FontFamily defaultFontFamily = new FontFamily("宋体");

        private static BaseTextFormat formatBrush = null;

        /// <summary>
        /// 全局文本块格式刷。
        /// </summary>
        public static BaseTextFormat BaseTextFormatBrush
        {
            get { return Globals.formatBrush; }
            set
            {
                Globals.formatBrush = value;

                Globals.isDraging = false;//否则会与拖动冲突。
                Globals.dragSourceExpression = null;
            }
        }

        public static Popup colorPickerPopup = new Popup() { IsOpen = false };

        public enum ArrowKeyMode { SelectExpression, ScrollEditor }

        public static ArrowKeyMode arrowKeyMode = ArrowKeyMode.SelectExpression;

        public static void SetBaseTextHeaderLevel(int fontSizeLevel)
        {
            //if (Globals.selectedEditor == null) return;
            //if (Globals.selectedEditor.SelectedExpression == null) return;

            //if (Globals.selectedEditor.SelectedExpression is Expressions.BaseText == false &&
            //    Globals.selectedEditor.SelectedExpression is Expressions.MarkText == false) return;

            //如果不是文本块或上下标式，则会是禁用。
            if (Globals.MainWindow.cbTextHeaderLevel.IsEnabled == false)
            {
                //因为并不是只有文本块才有“清除格式操作”，所以不能给这个消息框。
                //MessageBox.Show("请选中一个文本块或上下标式，然后再执行此操作！",
                //    Globals.appName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            Globals.MainWindow.cbTextHeaderLevel.SelectedIndex = fontSizeLevel;
        }

        public static string GetChineseNumber(int num)
        {
            string numStr = num.ToString();
            numStr = numStr.Replace('0', '〇');
            numStr = numStr.Replace('1', '一');
            numStr = numStr.Replace('2', '二');
            numStr = numStr.Replace('3', '三');
            numStr = numStr.Replace('4', '四');
            numStr = numStr.Replace('5', '五');
            numStr = numStr.Replace('6', '六');
            numStr = numStr.Replace('7', '七');
            numStr = numStr.Replace('8', '八');
            numStr = numStr.Replace('9', '九');
            return numStr;
        }

        public static Expressions.BaseText GetFstBaseText(Expressions.Expression ex)
        {
            if (ex == null) return null;

            if (ex is Expressions.Grid)
            {
                Expressions.Grid grid = ex as Expressions.Grid;

                return GetFstBaseText(grid.FirstSubPanel);
            }
            else if (ex is Expressions.SubPanel)
            {
                Expressions.SubPanel sPanel = ex as Expressions.SubPanel;
                foreach (UIElement ue in sPanel.BasePanel.Children)
                {
                    Expressions.BaseText resultBaseText = ue as Expressions.BaseText;

                    if (resultBaseText != null) return resultBaseText;

                    Expressions.Expression childEx = ue as Expressions.Expression;

                    if (childEx != null)
                    {
                        resultBaseText = GetFstBaseText(childEx);
                        if (resultBaseText != null) return resultBaseText;
                    }
                    else return null;
                }

                return null;
            }
            else
            {
                if (ex is Expressions.BaseText) return ex as Expressions.BaseText;

                if (ex is ICollapsed)
                {
                    if ((ex as ICollapsed).IsCollapsed
                        && (ex is Expressions.Expander == false)) return null;
                }

                if (ex.SubPanels != null)
                {
                    foreach (Expressions.SubPanel p in ex.SubPanels)
                    {
                        if (p.ParentExpression != null &&
                            (p.ParentExpression is Expressions.Expander))
                        {
                            Expressions.Expander pExpander = p.ParentExpression as Expressions.Expander;
                            if (pExpander.IsCollapsed && pExpander.SlavePanel == p)
                            {
                                continue;//如果此面板被隐藏，则跳过。
                            }
                        }

                        Expressions.BaseText rb = GetFstBaseText(p);
                        if (rb != null) return rb;
                    }
                }

                return null;
            }
        }

        public static TextCmdList textCmdList;
    }
}
